package net.lab1024.robot;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.lab1024.robot.type.DingTalkRobotMsg;
import net.lab1024.robot.type.DingTalkRobotMsgMarkdown;
import net.lab1024.robot.type.DingTalkRobotMsgText;
import net.lab1024.util.HttpClientUtil;
import net.lab1024.util.StringUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.HttpClient;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 钉钉推送业务
 *
 * @author listen
 * @date 2019/07/16 15:16
 */
public class DingTalkRobotNotify {

    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 钉钉群机器人 url
     */
    private String dingRobotUrl;

    /**
     * 签名密钥
     */
    private String secret;

    private HttpClientUtil httpClientUtil;

    public DingTalkRobotNotify(String dingRobotUrl, String secret, HttpClient httpClient) {
        this.dingRobotUrl = dingRobotUrl;
        this.secret = secret;
        this.threadPoolExecutor = this.initThreadPool();
        this.httpClientUtil = new HttpClientUtil(httpClient);
    }

    private ThreadPoolExecutor initThreadPool() {
        int processors = Runtime.getRuntime().availableProcessors();
        return new ThreadPoolExecutor(processors, processors, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
    }

    /**
     * 发送钉钉群机器人消息推送
     *
     * @param msg
     * @return
     */
    public String sendNotify(DingTalkRobotMsg msg) {
        // 校验消息体
        String checkType = this.checkType(msg);
        if (null != checkType) {
            return checkType;
        }
        HashMap<String, Object> param = new HashMap<>(3);
        // 确定消息类型
        String msgType = msg.getMsgType().toString().toLowerCase();
        param.put("msgtype", msgType);
        param.put(msgType, msg);
        // 是否 @ 所有人
        JSONObject atAllJSON = new JSONObject();
        atAllJSON.put("isAtAll", msg.getAtAll());
        param.put("at", atAllJSON);
        threadPoolExecutor.execute(() -> {
            // 生成签名
            long timeMillis = System.currentTimeMillis();
            String signature = generateSignature(timeMillis);
            httpClientUtil.postWithJSON(dingRobotUrl + "&timestamp=" + timeMillis + "&sign=" + signature, JSON.toJSONString(param));
        });
        return "OK";
    }

    /**
     * 校验消息内容是否合法
     *
     * @param msg
     * @return
     */
    private String checkType(DingTalkRobotMsg msg) {

        if (msg instanceof DingTalkRobotMsgText) {
            DingTalkRobotMsgText text = (DingTalkRobotMsgText) msg;
            if (StringUtil.isBlank(text.getContent())) {
                return "content not null !";
            }

        }

        if (msg instanceof DingTalkRobotMsgMarkdown) {
            DingTalkRobotMsgMarkdown markdown = (DingTalkRobotMsgMarkdown) msg;
            if (StringUtil.isBlank(markdown.getTitle())) {
                return "title not null !";
            }
            if (StringUtil.isBlank(markdown.getText())) {
                return "text not null !";
            }
        }

        return null;
    }

    /**
     * 生成签名
     *
     * @return
     */
    private String generateSignature(Long timestamp) {
        String stringToSign = timestamp + "\n" + secret;
        String encode = null;
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            encode = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encode;
    }
}
